﻿using FMALog;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;

namespace FMAPortalBase
{
    public static class ExtentionMethods
    {

        private static readonly string privateKey = "<RSAKeyValue><Modulus>uznzVPilsR1rWPkpq6m6IALaafDnVZTDDcnEyBD3A/PBx2JZTKM0DTgiTDDwCEmQBNBpPILcIBdtg3aSUgicair+2ksYrVFT+uiy0Zy1nU6qoJ+SsapLKrpCa1zHpV4LMO/pFo4Foqzw0C1FNe56FXo1xj77GPgeYl0MHUVtAUc=</Modulus><Exponent>AQAB</Exponent><P>+jPKs9JxpCSzNY+YNanz49Eo/A6RaU1DZWoFm/bawffZOompeL1jzpUlJUIrKVZJkNFvlxE90uXVwjxWBLv9BD==</P><Q>v5CVWKZ5Wo7W0QyoEOQS/OD8tkKS9DjzZnbnuo6lhcMaxsBrCWLstac1Xm2oFNtZgLtrPGbPfCNC5Su4Rz/P5w==</Q><DP>ZnyikmgobqEt20m3gnvcUDxT+nOJMsYYTklQhONoFj4M+EJ9bdy+Lle/gHSLM4KJ3c08VXgVh/bnSYnnfkb20Q==</DP><DQ>sSYGRfWk0W64Dpfyr7QKLxnr+Kv186zawU2CG44gWWNEVrnIAeUeWxnmi41CWw9BZH9sum2kv/pnuT/F6PWEzw==</DQ><InverseQ>XpWZQKXa1IXhF4FX3XRXVZGnIQP8YJFJlSiYx6YcdZF24Hg3+Et6CZ2/rowMFYVy+o999Y5HDC+4Qa1yWvW1vA==</InverseQ><D>Kkfb+8RrJqROKbma/3lE3xXNNQ7CL0F5CxQVrGcN8DxL9orvVdyjlJiopiwnCLgUHgIywceLjnO854Q/Zucq6ysm2ZRq36dpGLOao9eg+Qe8pYYO70oOkEe1HJCtP1Laq+f3YK7vCq7GkgvKAI9uzOd1vjQv7tIwTIADK19ObgE=</D></RSAKeyValue>";
        private static readonly int keySize = 1024;

        public static String ToJson(this Object sb)
        {
            try
            {
                String json = (new JavaScriptSerializer()).Serialize(sb);
                return json;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public static void DeSerialize<T>(this String json, ref T obj) where T : new()
        {
            try
            {
                obj = new JavaScriptSerializer().Deserialize<T>(json);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public static void DeSerialize<T>(this StringBuilder json,ref T obj) where T : new()
        {
            try
            {
                DeSerialize<T>(json.ToString(), ref obj);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public static T DeSerialize<T>(this StringBuilder json) where T : new()
        {
            T obj = new T();
            DeSerialize<T>(json, ref obj);
            return obj;
        }
        public static T DeSerialize<T>(this String json) where T : new()
        {
            T obj = new T();
            DeSerialize<T>(json.ToString(), ref obj);
            return obj;
        }

        public static String Hash(this String text)
        {
            using (SHA512 shaM = new SHA512Managed())
            {
                byte[] data = Encoding.UTF8.GetBytes(text);
                byte[] hash = shaM.ComputeHash(data);
                return Encoding.UTF8.GetString(hash);
            }
        }

        public static string EncryptString(this String inputString)
        {
            string xmlString = ExtentionMethods.privateKey;
            int dwKeySize = ExtentionMethods.keySize;
            // TODO: Add Proper Exception Handlers
            RSACryptoServiceProvider rsaCryptoServiceProvider =
                                          new RSACryptoServiceProvider(dwKeySize);
            rsaCryptoServiceProvider.FromXmlString(xmlString);
            int keySize = dwKeySize / 8;
            byte[] bytes = Encoding.UTF32.GetBytes(inputString);
            // The hash function in use by the .NET RSACryptoServiceProvider here 
            // is SHA1
            // int maxLength = ( keySize ) - 2 - 
            //              ( 2 * SHA1.Create().ComputeHash( rawBytes ).Length );
            int maxLength = keySize - 42;
            int dataLength = bytes.Length;
            int iterations = dataLength / maxLength;
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i <= iterations; i++)
            {
                byte[] tempBytes = new byte[
                        (dataLength - maxLength * i > maxLength) ? maxLength :
                                                      dataLength - maxLength * i];
                Buffer.BlockCopy(bytes, maxLength * i, tempBytes, 0,
                                  tempBytes.Length);
                byte[] encryptedBytes = rsaCryptoServiceProvider.Encrypt(tempBytes,
                                                                          true);
                // Be aware the RSACryptoServiceProvider reverses the order of 
                // encrypted bytes. It does this after encryption and before 
                // decryption. If you do not require compatibility with Microsoft 
                // Cryptographic API (CAPI) and/or other vendors. Comment out the 
                // next line and the corresponding one in the DecryptString function.
                Array.Reverse(encryptedBytes);
                // Why convert to base 64?
                // Because it is the largest power-of-two base printable using only 
                // ASCII characters
                stringBuilder.Append(Convert.ToBase64String(encryptedBytes));
            }
            return stringBuilder.ToString();
        }

        public static String DecryptString(this String inputString)
        {

            int dwKeySize = ExtentionMethods.keySize;
            string xmlString = ExtentionMethods.privateKey;
            // TODO: Add Proper Exception Handlers
            RSACryptoServiceProvider rsaCryptoServiceProvider
                                     = new RSACryptoServiceProvider(dwKeySize);
            rsaCryptoServiceProvider.FromXmlString(xmlString);
            int base64BlockSize = ((dwKeySize / 8) % 3 != 0) ?
              (((dwKeySize / 8) / 3) * 4) + 4 : ((dwKeySize / 8) / 3) * 4;
            int iterations = inputString.Length / base64BlockSize;
            ArrayList arrayList = new ArrayList();
            for (int i = 0; i < iterations; i++)
            {
                byte[] encryptedBytes = Convert.FromBase64String(
                     inputString.Substring(base64BlockSize * i, base64BlockSize));
                // Be aware the RSACryptoServiceProvider reverses the order of 
                // encrypted bytes after encryption and before decryption.
                // If you do not require compatibility with Microsoft Cryptographic 
                // API (CAPI) and/or other vendors.
                // Comment out the next line and the corresponding one in the 
                // EncryptString function.
                Array.Reverse(encryptedBytes);
                arrayList.AddRange(rsaCryptoServiceProvider.Decrypt(
                                    encryptedBytes, true));
            }
            return Encoding.UTF32.GetString(arrayList.ToArray(
                                      Type.GetType("System.Byte")) as byte[]);
        }

        public static void WriteLog(this Exception exc)
        {
            LogManager log = new LogManager(Const.ROOT_PATH + "\\Log");
            log.WriteLog(exc);
        }
        public static void WriteLog(this String str, LogType type)
        {
            LogManager log = new LogManager(Const.ROOT_PATH + "\\Log");
            log.WriteLog(str, type);
        }

    }
}
